package js.web.center.web;

import java.net.InetSocketAddress;

import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.session.DefaultSessionIdManager;
import org.eclipse.jetty.server.session.HouseKeeper;
import org.eclipse.jetty.server.session.SessionCache;
import org.eclipse.jetty.server.session.SessionCacheFactory;
import org.eclipse.jetty.server.session.SessionDataStore;
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.webapp.WebAppContext;

import js.web.center.core.config.JsWebConfig;

/**
 * 
 * @author dowell
 *
 */
public class JsWebServer {
	public static int DEFAULT_MAX_INACTIVE = 30;
	public static int DEFAULT_SCAVENGE_SEC = 10;
	public static int DEFAULT_EVICTIONPOLICY = SessionCache.NEVER_EVICT;

	protected static long workers = 0;

	protected final Server server;
	protected final int maxInactivePeriod;
	protected final int scavengePeriod;
	protected final ContextHandlerCollection contexts;
	protected SessionIdManager sessionIdManager;
	private HouseKeeper housekeeper;
	protected SessionCacheFactory cacheFactory;
	protected SessionDataStoreFactory storeFactory;

	public static String extractSessionId(String sessionCookie) {
		if (sessionCookie == null) {
			return null;
		}
		sessionCookie = sessionCookie.trim();
		int i = sessionCookie.indexOf(';');
		if (i >= 0) {
			sessionCookie = sessionCookie.substring(0, i);
		}
		if (sessionCookie.startsWith(JsWebConfig.httpSessionId)) {
			sessionCookie = sessionCookie.substring("JSESSIONID=".length());
		}
		i = sessionCookie.indexOf(JsWebConfig.CHECK_STATIC_SIGN);
		if (i >= 0) {
			sessionCookie = sessionCookie.substring(0, i);
		}
		return sessionCookie;
	}

	public JsWebServer(int port, int maxInactivePeriod, int scavengePeriod, SessionCacheFactory cacheFactory,
			SessionDataStoreFactory storeFactory) throws Exception {
		InetSocketAddress inetSocketAddress=new InetSocketAddress(JsWebConfig.httpBindIp, port);
		this.server = new Server(inetSocketAddress);
		this.maxInactivePeriod = maxInactivePeriod;
		this.scavengePeriod = scavengePeriod;
		this.cacheFactory = cacheFactory;
		this.storeFactory = storeFactory;
		this.contexts = new ContextHandlerCollection();
		this.sessionIdManager = newSessionIdManager();
		this.server.setSessionIdManager(this.sessionIdManager);
		((DefaultSessionIdManager) this.sessionIdManager).setServer(this.server);
		this.housekeeper = new HouseKeeper();
		this.housekeeper.setIntervalSec(this.scavengePeriod);
		((DefaultSessionIdManager) this.sessionIdManager).setSessionHouseKeeper(this.housekeeper);
	}

	public SessionIdManager newSessionIdManager() {
		DefaultSessionIdManager idManager = new DefaultSessionIdManager(getServer());
		idManager.setWorkerName("w" + (workers++));
		return idManager;
	}

	public SessionHandler newSessionHandler() throws Exception {
		SessionHandler handler = new SessionHandler();
		SessionCache cache = this.cacheFactory.getSessionCache(handler);
		SessionDataStore session = this.storeFactory.getSessionDataStore(handler);
		cache.setSessionDataStore(session);
		handler.setSessionCache(cache);
		return handler;
	}

	public void start() throws Exception {
		this.server.setHandler(this.contexts);
		this.server.start();
	}

	public HouseKeeper getHouseKeeper() {
		return this.housekeeper;
	}

	public int getPort() {
		return ((NetworkConnector) getServer().getConnectors()[0]).getLocalPort();
	}

	public ServletContextHandler addContext(String contextPath) throws Exception {
		ServletContextHandler context = new ServletContextHandler(this.contexts, contextPath);
		SessionHandler sessionHandler = newSessionHandler();
		sessionHandler.setSessionIdManager(this.sessionIdManager);
		sessionHandler.setMaxInactiveInterval(this.maxInactivePeriod);
		context.setSessionHandler(sessionHandler);
		return context;
	}

	public void stop() throws Exception {
		this.server.stop();
	}

	public WebAppContext addWebAppContext(String warPath, String contextPath) throws Exception {
		WebAppContext context = new WebAppContext(this.contexts, warPath, contextPath);
		SessionHandler sessionHandler = newSessionHandler();
		sessionHandler.setSessionIdManager(this.sessionIdManager);
		sessionHandler.setMaxInactiveInterval(this.maxInactivePeriod);
		context.setSessionHandler(sessionHandler);
		return context;
	}

	public Server getServer() {
		return this.server;
	}
}
